package com.seal.commons.infrastructure.redis.distributed.limiter;

import com.seal.commons.infrastructure.facade.distributed.limiter.DistributedRateLimiter;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.*;

import java.util.concurrent.TimeUnit;

/**
 * 功能描述: <br/>
 *
 * @author yong.huang
 * @date: 2020-07-24 17:08<br/>
 * @since JDK 1.8
 */
@Slf4j
public class RedisDistributedRateLimiter implements DistributedRateLimiter {

    private RedissonClient redissonClient;

    public RedisDistributedRateLimiter(RedissonClient redissonClient){
        this.redissonClient = redissonClient;
    }

    @Override
    public boolean tryAcquire(String key, long rate, long period, TimeUnit unit, boolean isCluster) {
        RateType type = isCluster ? RateType.OVERALL : RateType.PER_CLIENT;
        RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
        period = unit.toSeconds(period);
        if(rateLimiter.isExists()){
            RateLimiterConfig config = rateLimiter.getConfig();
            if(!config.getRateType().equals(type) || config.getRate() != rate || config.getRateInterval() != TimeUnit.MILLISECONDS.convert(period, TimeUnit.SECONDS)){
                log.warn("RedisDistributedRateLimiter :[{}] config changed", key);
                rateLimiter.delete();
                rateLimiter.trySetRate(type, rate, period, RateIntervalUnit.SECONDS);
            }
        }else{
            rateLimiter.trySetRate(type, rate, period, RateIntervalUnit.SECONDS);
        }
        return rateLimiter.tryAcquire();
    }
}